package net.cyue.easyconfiguration.json.util;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;
import java.util.logging.Logger;

/**
 * JSON工具类
 */
public final class JSONUtil {

    private static final Logger LOGGER = Logger.getLogger(JSONUtil.class.getName());
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    static {
        OBJECT_MAPPER.enable(
            JsonParser.Feature.ALLOW_COMMENTS,
            JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,
            JsonParser.Feature.ALLOW_SINGLE_QUOTES,
            JsonParser.Feature.ALLOW_YAML_COMMENTS,
            JsonParser.Feature.ALLOW_TRAILING_COMMA // 尾随逗号
        );
        OBJECT_MAPPER.setVisibility(
            PropertyAccessor.ALL,
            JsonAutoDetect.Visibility.ANY
        );
    }

    /**
     * 获取默认的ObjectMapper
     * @return 默认的ObjectMapper
     */
    public static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }

    /**
     * 将对象转为JSON字符串
     * @param obj 对象
     * @return JSON字符串
     */
    public static String toJSONString(Object obj) {
        try {
            return JSONUtil.OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 将JSON字符串转为对象
     * @param <T> 目标类型
     * @param text JSON字符串
     * @param clz 目标类
     * @return 目标对象
     */
    public static <T> T parseObject(String text, Class<T> clz) {
        try {
            return JSONUtil.OBJECT_MAPPER.readValue(text, clz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 将JSON字符串解析为JsonNode
     * @param json JSON字符串
     * @return 解析后的JsonNode
     * @throws JsonProcessingException 如果解析失败
     */
    public static JsonNode parse(String json) throws JsonProcessingException {
        return OBJECT_MAPPER.readTree(json);
    }


    /**
     * 获取JsonNode的所有字段名称
     * @param node JsonNode
     * @return 字段名称列表
     */
    public static List<String> getObjectFieldNameList(JsonNode node) {
        if (node == null) {
            LOGGER.warning("Invalid object: null");
            return Collections.emptyList();
        }
        List<String> fieldNames = new ArrayList<>();
        if (node.isObject()) {
            node.fieldNames().forEachRemaining(fieldNames::add);
        } else {
            LOGGER.warning("Invalid object: " + node);
        }
        return fieldNames;
    }


    /**
     * 获取指定路径的JsonNode
     * @param node 父JsonNode
     * @param path 字段路径，支持嵌套，如"user.addresses[0]"，为空返回原 node
     * @return 对应的 JsonNode，如果不存在则返回 null
     */
    public static JsonNode getNode(JsonNode node, String path) {
        if (node == null || path == null || path.isEmpty()) {
            return node;
        }

        String[] pathSegments = path.split("\\.");
        JsonNode current = node;

        for (String segment : pathSegments) {
            // 处理数组索引，如"addresses[0]"
            if (segment.contains("[")) {
                String fieldName = segment.substring(0, segment.indexOf("["));
                int index = Integer.parseInt(segment.substring(
                        segment.indexOf("[") + 1,
                        segment.indexOf("]")
                ));

                current = current.get(fieldName);
                if (current == null || !current.isArray() || index < 0 || index >= current.size()) {
                    return null;
                }
                current = current.get(index);
            } else {
                current = current.get(segment);
            }

            if (current == null) {
                return null;
            }
        }

        return current;
    }

    /**
     * 转换单个JsonNode的值，递归处理所有类型
     * @param valueNode 要转换的JsonNode
     * @return 转换后的值
     */
    public static Object convertNode2Value(JsonNode valueNode) {
        // 处理节点不存在的情况
        if (valueNode == null) {
            return null;
        }

        // 处理null值
        if (valueNode.isNull()) {
            return null;
        }

        // 处理文本类型
        if (valueNode.isTextual()) {
            return valueNode.asText();
        }

        // 处理数字类型
        if (valueNode.isNumber()) {
            return valueNode.numberValue();
        }

        // 处理布尔类型
        if (valueNode.isBoolean()) {
            return valueNode.booleanValue();
        }

        // 处理数组类型
        if (valueNode.isArray()) {
            List<Object> list = new ArrayList<>();
            for (JsonNode element : valueNode) {
                // 递归处理数组元素
                list.add(convertNode2Value(element));
            }
            return list.toArray();
        }

        // 处理对象类型，转为Map并递归处理内部字段
        if (valueNode.isObject()) {
            Map<String, Object> map = new HashMap<>();
            valueNode.fieldNames().forEachRemaining(fieldName -> {
                JsonNode fieldNode = valueNode.get(fieldName);
                // 递归处理每个字段值
                map.put(fieldName, convertNode2Value(fieldNode));
            });
            return map;
        }

        // 其他类型（如二进制等）
        return valueNode.asText();
    }

    /**
     * 获取指定路径节点的值，递归处理所有类型
     * @param node 父JsonNode
     * @param path 字段路径
     * @return 节点值，对象会转为Map，数组转为List，基本类型保持对应Java类型
     */
    public static Object getNodeValue(JsonNode node, String path) {
        JsonNode valueNode = getNode(node, path);
        return convertNode2Value(valueNode);
    }


    /**
     * 获取指定路径的字符串字段值
     * @param node 父JsonNode
     * @param path 字段路径，支持嵌套，如"user.name"
     * @return 字段值，如果字段不存在或为null则返回null
     */
    public static String getString(JsonNode node, String path) {
        JsonNode valueNode = getNode(node, path);
        return valueNode != null && !valueNode.isNull() ? valueNode.asText() : null;
    }

    /**
     * 获取指定路径的字符串字段值，若不存在则返回默认值
     * @param node 父JsonNode
     * @param path 字段路径
     * @param defaultValue 默认值
     * @return 字段值或默认值
     */
    public static String getString(JsonNode node, String path, String defaultValue) {
        String value = getString(node, path);
        return value != null ? value : defaultValue;
    }

    /**
     * 获取指定路径的数字字段值
     * @param node 父JsonNode
     * @param path 字段路径
     * @return 字段值，如果字段不存在、为null或无法转换则返回null
     */
    public static Number getNumber(JsonNode node, String path) {
        return getNumber(node, path, null);
    }
    /**
     * 获取指定路径的数字字段值
     * @param node 父JsonNode
     * @param path 字段路径
     * @return 字段值，如果字段不存在、为null或无法转换则返回null
     */
    public static Number getNumber(JsonNode node, String path, Number defaultValue) {
        JsonNode valueNode = getNode(node, path);
        if (valueNode != null && !valueNode.isNull() && valueNode.isNumber()) {
            return valueNode.numberValue();
        }
        LOGGER.warning("Invalid number value: " + path);
        return defaultValue;
    }


    /**
     * 获取指定路径的boolean字段值
     * @param node 父JsonNode
     * @param path 字段路径
     * @return 字段值，如果字段不存在或为null则返回false
     */
    public static boolean getBoolean(JsonNode node, String path) {
        return getBoolean(node, path, false);
    }

    /**
     * 获取指定路径的boolean字段值，若不存在或为null则返回默认值
     * @param node 父JsonNode
     * @param path 字段路径
     * @param defaultValue 默认值
     * @return 字段值或默认值
     */
    public static Boolean getBoolean(JsonNode node, String path, Boolean defaultValue) {
        JsonNode valueNode = getNode(node, path);
        if (valueNode != null && !valueNode.isNull() && valueNode.isBoolean()) {
            return valueNode.asBoolean();
        }
        LOGGER.warning("Invalid boolean value: " + path);
        return defaultValue;
    }

    /**
     * 获取指定路径的JSON数组，并转换为通用对象列表
     * 与getList的区别是：此方法不要求元素是特定类型，使用convertNode2Value递归转换
     * @param node 父JsonNode
     * @param path 字段路径
     * @return 转换后的对象列表，如果字段不存在或不是数组则返回空列表
     */
    public static List<Object> getArray(JsonNode node, String path) {
        JsonNode arrayNode = getNode(node, path);

        if (arrayNode == null || !arrayNode.isArray()) {
            LOGGER.warning("Path is not an array or does not exist: " + path);
            return Collections.emptyList();
        }

        List<Object> result = new ArrayList<>();
        for (JsonNode element : arrayNode) {
            result.add(convertNode2Value(element));
        }
        return result;
    }

    /**
     * 获取指定路径的对象数据，仅处理 Object 节点并转换为 Map
     * @param node 父 JsonNode
     * @param path 字段路径
     * @return 返回 Object 转换后的 Map 数据
     */
    public static Map<String, Object> getTable(JsonNode node, String path) {
        JsonNode objectNode = getNode(node, path);

        // 检查路径是否指向一个数组
        if (objectNode == null || !objectNode.isObject()) {
            LOGGER.warning("Path is not an object or does not exist: " + path);
            return new HashMap<>();
        }

        Map<String, Object> map = new HashMap<>();
        // 遍历对象的所有字段并转换
        objectNode.fieldNames().forEachRemaining(fieldName -> {
            JsonNode fieldNode = objectNode.get(fieldName);
            map.put(fieldName, convertNode2Value(fieldNode));
        });
        return map;
    }


    /**
     * 获取指定路径的JSON数组，并转换为指定类型的列表
     * @param node 父JsonNode
     * @param path 字段路径
     * @param clazz 目标类型的Class对象
     * @param <T> 目标类型
     * @return 转换后的列表，如果字段不存在、不是数组或转换失败则返回空列表
     */
    public static <T> List<T> getList(JsonNode node, String path, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        JsonNode arrayNode = getNode(node, path);

        if (arrayNode == null || !arrayNode.isArray()) {
            return result;
        }

        for (JsonNode element : arrayNode) {
            try {
                T value = OBJECT_MAPPER.treeToValue(element, clazz);
                result.add(value);
            } catch (JsonProcessingException e) {
                // 转换失败时跳过该元素
                LOGGER.warning("Invalid element in array: " + path);
                LOGGER.warning(e.toString());
            }
        }

        return result;
    }

    /**
     * 将JsonNode转换为指定类型的对象
     * @param node 要转换的JsonNode
     * @param clazz 目标类型的Class对象
     * @param <T> 目标类型
     * @return 转换后的对象，如果转换失败则返回null
     */
    public static <T> T convertValue(JsonNode node, Class<T> clazz) {
        if (node == null || clazz == null) {
            return null;
        }

        try {
            return OBJECT_MAPPER.treeToValue(node, clazz);
        } catch (JsonProcessingException e) {
            LOGGER.warning("Failed to convert JsonNode to " + clazz.getName());
            LOGGER.warning(e.toString());
            return null;
        }
    }


    public static void main(String[] args) throws JsonProcessingException {
        StringBuilder sb = new StringBuilder("{");
        sb.append("name:\"John\",");
        sb.append("age:30,");
        sb.append("city:\"New York\",");
        sb.append("description: 'hello',");
        sb.append("}");
        JsonNode node = JSONUtil.parse(sb.toString());
        System.out.println(node.toString());

        // 测试嵌套JSON结构
        String json = "{" +
                "\"name\":\"John\"," +
                "\"age\":30," +
                "\"address\":{" +
                "\"city\":\"New York\"," +
                "\"zipCode\":10001" +
                "}," +
                "\"hobbies\":[\"reading\", \"sports\"]," +
                "\"scores\":{" +
                "\"math\":95.5," +
                "\"english\":88" +
                "}" +
                "}";

        node = JSONUtil.parse(json);
        Object result = JSONUtil.getNodeValue(node, "");
        System.out.println("Full JSON converted to Map: " + result);

        // 测试获取嵌套对象
        Object address = JSONUtil.getNodeValue(node, "address");
        System.out.println("Address as Map: " + address);
    }
}

